from thingsboard_gateway.connectors.mqtt.mqtt_uplink_converter import MqttUplinkConverter
from thingsboard_gateway.extensions.mqtt.mqtt_utils import convert_time
from thingsboard_gateway.gateway.entities.converted_data import ConvertedData
from thingsboard_gateway.gateway.entities.telemetry_entry import TelemetryEntry
from thingsboard_gateway.gateway.statistics.decorators import CollectStatistics
from thingsboard_gateway.gateway.statistics.statistics_service import StatisticsService
# {
#   "did": "FI7300351157",
#   "utime": "2024/11/05 10:43:05",
#   "content": [
#     {
#       "pid": "1",
#       "type": "0",
#       "addr": "T",
#       "addrv": "10086",
#       "ctime": "2024/11/05 10:43:05"
#     },
#     {
#       "pid": "1",
#       "type": "0",
#       "addr": "EPC",
#       "addrv": "10010.000",
#       "ctime": "2024/11/05 10:43:05"
#     }
#   ]
# }


class CustomMqttArrayUplinkConverter(MqttUplinkConverter):
    def __init__(self, config, logger):
        super().__init__()
        self._log = logger

        cfg = config.get("converter", {})
        ext = cfg.get("extensionConfig", {})

        # 通用配置
        self.prefix = ext.get("prefixKey", "")
        self.device_id_key = ext.get("deviceIdKey", "pid")
        self.device_type = ext.get("deviceType", "Default_Device")

        # 遥测相关
        self.data_key = ext.get("telemetryDataKey", "content")
        self.addr_key = ext.get("telemetryAddrKey", "addr")
        self.value_key = ext.get("telemetryAddrValueKey", "addrv")
        self.ts_key = ext.get("timestampKey", "ctime")

        # telemetryKeys = null → 接受所有
        keys = ext.get("telemetryKeys")
        self.allowed_keys = set(keys) if keys is not None else None

    # ==========================================================
    #                    转换主逻辑
    # ==========================================================
    @CollectStatistics(start_stat_type='receivedBytesFromDevices',
                       end_stat_type='convertedBytesFromDevice')
    def convert(self, topic, body):
        device_map = {}

        records = body.get(self.data_key, [])
        if not isinstance(records, list):
            self._log.error(
                f"Telemetry array '{self.data_key}' must be list, got {type(records).__name__}"
            )
            return []

        for record in records:
            # -------------------------------
            # 1. 设备 ID 提取
            # -------------------------------
            device_id = record.get(self.device_id_key)
            if not device_id:
                preview = dict(list(record.items())[:3])
                self._log.error(
                    f"Missing deviceId '{self.device_id_key}' in record: {preview}"
                )
                continue

            # 生成最终设备名称（prefix + id）
            full_name = f"{self.prefix}{device_id}"

            # -------------------------------
            # 2. 时间戳转换
            # -------------------------------
            timestamp = convert_time(record.get(self.ts_key))

            # -------------------------------
            # 3. 遥测键/值
            # -------------------------------
            addr = record.get(self.addr_key)
            if self.allowed_keys is not None and addr not in self.allowed_keys:
                continue  # 不在允许列表中

            value = record.get(self.value_key)
            if value is None:
                self._log.debug(
                    f"Telemetry value missing for addr='{addr}' in device={full_name}"
                )
                continue

            # -------------------------------
            # 4. 获取/创建设备对象
            # -------------------------------
            device = device_map.get(full_name)
            if device is None:
                device = device_map[full_name] = ConvertedData(full_name, self.device_type)

            # -------------------------------
            # 5. 添加遥测数据（局部 try 保证异常不影响整个记录）
            # -------------------------------
            try:
                device.add_to_telemetry(TelemetryEntry({addr: value}, ts=timestamp))
            except Exception as e:
                self._log.debug(
                    f"Failed to add telemetry: device={full_name}, addr={addr}, "
                    f"value={value}, error={e}"
                )

        # ==========================================================
        #                     统计指标
        # ==========================================================
        attr_count = sum(d.attributes_datapoints_count for d in device_map.values())
        ts_count = sum(d.telemetry_datapoints_count for d in device_map.values())

        StatisticsService.count_connector_message(self._log.name, 'convertersAttrProduced', attr_count)
        StatisticsService.count_connector_message(self._log.name, 'convertersTsProduced', ts_count)

        return list(device_map.values())
